package com.apobates.jforum2.troll.notices.controller;

import com.apobates.jforum2.troll.notices.ForumLetterReplica;
import com.apobates.jforum2.troll.notices.biz.ForumLetterService;
import com.apobates.jforum2.troll.notices.biz.InboxService;
import com.apobates.jforum2.troll.notices.biz.OutboxService;
import com.apobates.jforum2.troll.notices.entity.ForumLetter;
import com.apobates.jforum2.troll.notices.entity.ForumLetterTypeEnum;
import com.apobates.jforum2.troll.notices.mapper.LetterDigestVoMapperEntity;
import com.apobates.jforum2.troll.notices.mapper.LetterInboxVoMapperEntity;
import com.apobates.jforum2.troll.notices.mapper.LetterOutboxVoMapperEntity;
import com.apobates.jforum2.troll.notices.stub.vo.LetterDigestVo;
import com.apobates.jforum2.troll.notices.stub.vo.LetterInboxNoticeVo;
import com.apobates.jforum2.troll.notices.stub.vo.LetterInboxVo;
import com.apobates.jforum2.troll.notices.stub.vo.LetterOutboxVo;
import com.apobates.jforum2.troll.utils.core.Commons;
import com.apobates.jforum2.troll.utils.core.EntityPageResult;
import com.apobates.jforum2.troll.utils.core.ResponseResult;
import com.apobates.jforum2.troll.utils.persistence.Page;
import com.apobates.jforum2.troll.utils.persistence.PageRequest;
import com.apobates.jforum2.troll.utils.persistence.Pageable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * 内部消息Api
 *
 * @author xiaofanku
 * @since 20201114
 */
@RestController
@RequestMapping("/letter")
public class LetterController {
    @Autowired
    private InboxService inboxService;
    @Autowired
    private OutboxService outboxService;
    @Autowired
    private ForumLetterService forumLetterService;
    private final static Logger logger = LoggerFactory.getLogger(LetterController.class);

    //1.指定日期以来未坊的信件
    @GetMapping("/recent/{member}/{sender}/{stamp}")
    public List<LetterDigestVo> getLetterForPrevious(
            @PathVariable("member") long memberId,
            @PathVariable("sender") long sender,
            @PathVariable("stamp") int previousUx){
        Stream<ForumLetter> rs = inboxService.get(sender, memberId, previousUx);
        return rs.map(fl->LetterDigestVoMapperEntity.mapper().apply(fl,memberId)).collect(Collectors.toList());
    }
    //2.聊天界面中的记录
    @GetMapping("/chat/{member}/{sender}/{page}/{number}")
    public EntityPageResult<LetterDigestVo> getMutualLetter(
            @PathVariable("member") long memberId,
            @PathVariable("sender") long sender,
            @PathVariable("page") int page,
            @PathVariable("number") int pageSize){
        Pageable pr = new PageRequest(page, pageSize);
        Page<ForumLetter> rs = forumLetterService.getMutualLetter(sender, memberId, pr);
        //
        ResponseResult<EntityPageResult<LetterDigestVo>> rr = ResponseResult.PageResultBuilder.<LetterDigestVo,ForumLetter>getInstance(page, pageSize)
                .from(rs.getTotalElements(), rs.getResult())
                .build(LetterDigestVoMapperEntity.mapper(), memberId);
        return rr.getData();
    }
    //3.会员的收件箱
    @GetMapping("/inbox/{member}/{page}/{number}")
    public EntityPageResult<LetterInboxVo> getLetterInbox(
            @PathVariable("member") long memberId,
            @PathVariable("page") int page,
            @PathVariable("number") int pageSize){
        Page<ForumLetter> rs = inboxService.getInBoxGroupSender(memberId, new PageRequest(page, pageSize));
        //
        ResponseResult<EntityPageResult<LetterInboxVo>> rr = ResponseResult.PageResultBuilder.<LetterInboxVo,ForumLetter>getInstance(page, pageSize)
                .from(rs.getTotalElements(), rs.getResult())
                .build(LetterInboxVoMapperEntity.mapper());
        return rr.getData();
    }

    //4.会员的发件箱
    @GetMapping("/outbox/{member}/{typed}/{page}/{number}")
    public EntityPageResult<LetterOutboxVo> getLetterOutbox(
            @PathVariable("member") long memberId,
            @PathVariable("typed") int typeEnumSymbol,
            @PathVariable("page") int page,
            @PathVariable("number") int pageSize){
        ForumLetterTypeEnum label = ForumLetterTypeEnum.getInstance(typeEnumSymbol).orElse(ForumLetterTypeEnum.ALL);
        Pageable pr = new PageRequest(page, pageSize);
        Page<ForumLetterReplica> rs = (ForumLetterTypeEnum.ALL == label) ? outboxService.getSent(memberId, pr) : outboxService.getSent(memberId, label, pr);
        //
        ResponseResult<EntityPageResult<LetterOutboxVo>> rr = ResponseResult.PageResultBuilder.<LetterOutboxVo,ForumLetterReplica>getInstance(page, pageSize)
                .from(rs.getTotalElements(), rs.getResult())
                .build(LetterOutboxVoMapperEntity.mapper());
        return rr.getData();
    }

    //5.发送消息
    @PostMapping(value="/sent", consumes="application/x-www-form-urlencoded")
    public ResponseEntity<LetterDigestVo> sendLetter(
            @RequestParam("sender")long sender,
            @RequestParam("nickname")String senderNickname,
            @RequestParam("subject")String subject,
            @RequestParam("message")String content,
            @RequestParam("receiver")long receiver,
            @RequestParam("receiverNickname")String receiverNickname){
        int code=500;
        long fid = forumLetterService.create(subject, content, receiver,receiverNickname, sender, senderNickname);
        if(fid>0L){
            code = 200;
        }
        LetterDigestVo data = new LetterDigestVo();
        data.setId(fid);
        data.setSender(sender);
        data.setNickname(senderNickname);
        data.setSubject(subject);
        data.setBody(content);
        data.setEntryDatetime(LocalDateTime.now());
        data.setReceiver(receiver);
        return ResponseEntity.status(code).contentType(MediaType.APPLICATION_JSON).body(data);
    }
    //6.收件箱中标记信件为已读
    @PutMapping(value = "/inbox/{member}/readed/all", consumes="application/x-www-form-urlencoded")
    public boolean readAllLetter(
            @PathVariable("member")long memberId,
            @RequestParam("target")long othMember,
            @RequestParam("direction")int direction){
        Optional<Boolean> r = inboxService.compositeReaded(memberId, othMember, direction);
        return r.orElse(false);
    }
    //7.收件箱中标记信件为已读
    @PutMapping(value = "/inbox/{member}/readed", consumes = "application/x-www-form-urlencoded")
    public boolean readedLetter(
            @PathVariable("member")long memberId,
            @RequestParam("records")String idString){
        List<Long> messageIdList = Commons.toLongList(idString);
        boolean r = inboxService.readed(memberId, messageIdList)>0;
        return r;
    }
    //8.收件箱中未读的信件数量
    @GetMapping("/inbox/{member}/unreaded/size")
    public long getUnReadLetterSize(@PathVariable("member")long memberId){
        return inboxService.countForMemberMessages(memberId);
    }

    //9.收件箱中指定发件人发来的未读的信件数量
    @GetMapping("/inbox/{member}/sender/{sender}/unreaded/size")
    public long getUnReadLetterSize(@PathVariable("member")long memberId, @PathVariable("sender")long senderId){
        return inboxService.countForMemberMessages(memberId, senderId);
    }

    //10.收件箱中发件人发来的未读数量
    @PostMapping(value="/inbox/{member}/unreaded", consumes="application/x-www-form-urlencoded")
    public Map<Long,Long> getInboxSenderUnreads(
            @PathVariable("member")long memberId,
            @RequestParam("records")String senderIdString){
        Set<Long> senderIdSet = Commons.toLongSet(senderIdString);
        Map<Long, Long> rs = inboxService.groupForMemberMessages(memberId, senderIdSet);
        return rs;
    }

    //11.收件箱中发件人发来的未读数量
    @PostMapping(value = "/inbox/{member}/unreaded/collect", consumes="application/x-www-form-urlencoded")
    public List<LetterInboxNoticeVo> getInboxSenderUnreadsCollect(
            @PathVariable("member")long memberId,
            @RequestParam("records")String senderIdString){
        Set<Long> senderIdSet = Commons.toLongSet(senderIdString);
        return inboxService.groupForMemberMessages(memberId, senderIdSet).entrySet().stream().map(entry->{
            LetterInboxNoticeVo lin = new LetterInboxNoticeVo();
            lin.setSender(entry.getKey());
            lin.setCount(entry.getValue());
            return lin;
        }).collect(Collectors.toList());
    }
    //12.今日的通知
    @GetMapping("/today/claim")
    public List<LetterDigestVo> getTodayClaim(){
        Stream<ForumLetter> rs = forumLetterService.getTodayClaim();
        return rs.map(fl->LetterDigestVoMapperEntity.mapper().apply(fl,0L)).collect(Collectors.toList());
    }
    //使用SSE获取指定收件人未读的消息
    /*Angular采用的
    @GET
    @Path("/inbox/{member}/notice")
    @Produces(MediaType.SERVER_SENT_EVENTS)
    public void getMessageUnreadNotice(@Context SseEventSink eventSink, @Context Sse sse, @PathParam("member") long memberId) {
        new Thread(() -> {
            while (!Thread.currentThread().isInterrupted()) { //判断是否被中断
                final OutboundSseEvent event = sse.newEventBuilder()
                        .name("UnReadMessages")
                        .data(Long.class, inboxService.countForMemberMessages(memberId))
                        .build();
                //CompletableFuture.runAsync(() -> eventSink.send(event)).whenComplete((r, ex) -> eventSink.close());
                //客户端close了
                if(!eventSink.isClosed()) {
                    eventSink.send(event);
                }else {
                    Thread.currentThread().interrupt();
                }
                try{
                    //5000 = 一分钟12次|三分钟一次
                    Thread.sleep(1000*60*3);
                }catch(InterruptedException e){
                    //浏览器关闭了
                    Thread.currentThread().interrupt(); //重新设置中断标示
                }
            }
        }).start();
    }*/
}
/*
/letter/recent/{member}/{sender}/{stamp}
/letter/outbox/{member}/{typed}/{page}/{number}
/letter/sent
/letter/chat/{member}/{sender}/{page}/{number}
/letter/inbox/{member}/{page}/{number}
/letter/inbox/{member}/readed/all
/letter/inbox/{member}/readed
/letter/inbox/{member}/unreaded/size
/letter/inbox/{member}/unreaded
/letter/inbox/{member}/unreaded/collect
/letter/inbox/{member}/sender/{sender}/unreaded/size
/letter/inbox/{member}/notice
/letter/today/claim
* */